// debug heap support header for Microsoft
#pragma once
#ifndef _XDEBUG_
#define _XDEBUG_
#ifndef RC_INVOKED
#include <yvals.h>

#ifdef _MSC_VER
 #pragma pack(push,_CRT_PACKING)
 #pragma warning(push,3)
#endif  /* _MSC_VER */

_STD_BEGIN
struct _DebugHeapTag_t
	{	// placement new tag type to select debug CRT heap
	int _Type;
	};
_STD_END

		// SUPPORT FOR DEBUG HEAP

 #if defined(_DEBUG)
   #define _NEW_CRT				new(std::_DebugHeapTag_func(), __FILE__, __LINE__)
   #define _DELETE_CRT(ptr)		std::_DebugHeapDelete(ptr)
   #define _DELETE_CRT_VEC(ptr)	std::_DebugHeapDelete((void *)ptr)
   #define _STRING_CRT			_DebugHeapString

  #include <crtdbg.h>
  #include <xmemory>
  #include <xstring>

_Ret_bytecap_(_Size) _MRTIMP2 void * __cdecl operator new(size_t _Size,
	const std::_DebugHeapTag_t&, _In_opt_z_ char *, int)
		_THROW_BAD_ALLOC;	// allocate from the debug CRT heap

_Ret_bytecap_(_Size) _MRTIMP2 void * __cdecl operator new[](size_t _Size,
	const std::_DebugHeapTag_t&, _In_opt_z_ char *, int)
		_THROW_BAD_ALLOC;	// allocate array from the debug CRT heap

_MRTIMP2 void __cdecl operator delete(void *,
	const std::_DebugHeapTag_t&, _In_opt_z_ char *, int)
		_THROW0();	// delete if new for debug CRT heap fails

_MRTIMP2 void __cdecl operator delete[](void *,
	const std::_DebugHeapTag_t&, _In_opt_z_ char *, int)
		_THROW0();	// delete if array new for debug CRT heap fails

_STD_BEGIN

_MRTIMP2 const _DebugHeapTag_t& __cdecl _DebugHeapTag_func();

		// TEMPLATE FUNCTION _DebugHeapDelete
template<class _Ty>
	void __CLRCALL_OR_CDECL _DebugHeapDelete(_Ty *_Ptr)
	{	// delete from the debug CRT heap even if operator delete exists
	if (_Ptr != 0)
		{	// worth deleting
		_Ptr->~_Ty();
		// delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
		// facets allocated by normal new.
		free(_Ptr);
		}
	}

		// TEMPLATE CLASS _DebugHeapAllocator
template<class _Ty>
	class _DebugHeapAllocator
	: public allocator<_Ty>
	{	// an allocator which uses the debug CRT heap
public:

	template<class _Other>
		struct rebind
		{	// convert _DebugHeapAllocator<_Ty> to _DebugHeapAllocator<_Other>
		typedef typename _DebugHeapAllocator<_Other> other;
		};

	typename allocator<_Ty>::pointer __CLRCALL_OR_CDECL allocate(typename allocator<_Ty>::size_type _Count, const void *)
		{	// check for integer overflow
		if (_Count <= 0)
			_Count = 0;
		else if (((size_t)(-1) / _Count) < sizeof(_Ty))
			_THROW_NCEE(std::bad_alloc, NULL);

			// allocate array of _Count elements, ignore hint
		return ((_Ty *)_NEW_CRT char[_Count * sizeof(_Ty)]);
		}

	typename allocator<_Ty>::pointer __CLR_OR_THIS_CALL allocate(typename allocator<_Ty>::size_type _Count)
		{	// check for integer overflow
		if (_Count <= 0)
			_Count = 0;
		else if (((size_t)(-1) / _Count) < sizeof(_Ty))
			_THROW_NCEE(std::bad_alloc, NULL);

			// allocate array of _Count elements
		return ((_Ty *)_NEW_CRT char[_Count * sizeof(_Ty)]);
		}

	void __CLR_OR_THIS_CALL deallocate(typename allocator<_Ty>::pointer _Ptr, typename allocator<_Ty>::size_type)
		{	// deallocate object at _Ptr, ignore size
		_DELETE_CRT_VEC(_Ptr);
		}
	};

template class _CRTIMP2_PURE _DebugHeapAllocator<char>;

		// CLASS _DebugHeapString
class _CRTIMP2_PURE _DebugHeapString
	: public basic_string<char, char_traits<char>, _DebugHeapAllocator<char> >
	{	// a version of std::string allocated on the debug CRT heap
public:
	typedef _DebugHeapString _Myt;
	typedef basic_string<char, char_traits<char>, _DebugHeapAllocator<char> >
		_Mybase;
	typedef char _Elem;

	__CLR_OR_THIS_CALL _DebugHeapString()
		: _Mybase()
		{	// construct empty string
		}

	__CLR_OR_THIS_CALL _DebugHeapString(const _Myt& _Right)
		: _Mybase(_Right)
		{	// construct by copying _Right
		}

	__CLR_OR_THIS_CALL _DebugHeapString(const _Elem *_Ptr)
		: _Mybase(_Ptr)
		{	// construct from [_Ptr, <null>)
		}

	__CLR_OR_THIS_CALL _DebugHeapString(const string &_Str)
		: _Mybase(_Str.c_str())
		{	// construct from std::string
		}

	__CLR_OR_THIS_CALL operator string() const
		{	// convert to a string
		return (string(c_str()));
		}
	};
_STD_END

  #else /* defined(_DEBUG) */
   #define _NEW_CRT				new
   #define _DELETE_CRT(ptr)		delete (ptr)
   #define _DELETE_CRT_VEC(ptr)	delete[] (ptr)
   #define _STRING_CRT			string
  #endif /* defined(_DEBUG) */


#ifdef _MSC_VER
 #pragma warning(pop)
 #pragma pack(pop)
#endif  /* _MSC_VER */


#endif /* RC_INVOKED */
#endif  /* _XDEBUG_ */

/*
 * Copyright (c) 1992-2007 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V5.03:0009 */
